package suites.queue {
	import suites.queue.mock.AsyncQable;

	import org.flexunit.asserts.assertEquals;
	import org.flexunit.asserts.assertFalse;
	import org.flexunit.asserts.assertTrue;
	import org.flexunit.asserts.fail;
	import org.flexunit.async.Async;
	import org.splink.library.queue.IQ;
	import org.splink.library.queue.Progress;
	import org.splink.library.queue.Q;
	import org.splink.library.queue.QEvent;

	import flash.events.Event;

	/**
	 * @author Max Kugland
	 */
	public class AbstractQTest {
		protected var _q : IQ;
		protected var _count : int;
		private var _handleEventFnc : Function;

		[Before]
		final public function before() : void {
			_count = 0;
			_q = qImpl("q");
			_q.register(QEvent.PROGRESS, onProgress);
			_q.register(QEvent.ERROR, onError);
			_q.register(QEvent.COMPLETE, onComplete);
		}
		
		/**
		 * Override in subclasses to use different <code>IQ</code> implementations
		 */
		protected function qImpl(id : String) : IQ {
			return new Q(id);
		}

		[After]
		final public function after() : void {
			_q.finalize();
			assertFalse(_q.isRunning);
			assertEquals(_q.length, 0);			assertEquals(Q.getTotal(_q), 0);			assertEquals(_q.id, "q");
			_q = null;
		}

		final protected function createQ(num : int) : IQ {
			var q : IQ = qImpl("q-" + _count.toString());
			_count++;
			for (var i : int = 0;i < num;i++) {
				q.add(new AsyncQable("i-" + _count.toString()));
				_count++;
			}
			return q;
		}

		final protected function handleAsync(timeout : int) : Function {
			return _handleEventFnc = Async.asyncHandler(this, function():void {
			}, timeout, null, handleTimeout);
		}

		private function handleTimeout( passThroughData : Object ) : void {
			fail("Timeout reached before event");			
		}

		private function onProgress(e : QEvent) : void {
			var qp : Progress = e.queueProgress;			assertTrue(qp.percent <= 100 && qp.percent >= 0);
			
			var p : Progress = e.progress;			assertTrue(p.percent <= 100 && p.percent >= 0);
//			trace(e.id + " -> " + p.percent + " - " + qp.percent)
		}

		private function onError(e : QEvent) : void {
			fail("queue error: " + e.errorMessage);
		}

		private function onComplete(e : QEvent) : void {
			_handleEventFnc(new Event(Event.COMPLETE));
		}
	}
}
